import {Browser, ElementHandle, launch, Page} from "puppeteer";

export class CommonUtils {
    /**
     * 等待一定时间
     *
     * @param {number} timeout
     * @returns {Promise<void>}
     */
    static sleep(timeout: number): Promise<void> {
        if (timeout < 0) timeout = 0;
        return new Promise<void>(resolve => {
            setTimeout(() => resolve(), timeout);
        });
    }

    /**
     * 进行页面刷新操作
     *
     * @param pages 页面列表
     */
    static refreshThePage(pages: Page[]): Promise<boolean> {
        return new Promise(async (resolve) => {
            for (let page of pages) {
                await page.bringToFront();
                await page.reload();
            }
            return resolve(true);
        });
    }

    /**
     * 获取浏览器
     *
     * 调用该方法，将会返回一个新的浏览器
     *
     * 如果打开失败，会向上抛出异常
     */
    static getBrowser(): Promise<Browser | null> {
        return new Promise<Browser | null>(async (resolve) => {
            let browser = null;
            try {
                // -- 浏览器配置 开始
                const width = 1200;
                const width2 = 1200;
                const height = 1000;
                const height2 = 600;
                const headless = true;
                const slowMo = 20;
                const timeout = 60000;
                const ignoreDefaultArgs = "--enable-automation";
                browser = await launch({
                    // @ts-ignore
                    ignoreDefaultArgs: ignoreDefaultArgs,
                    headless: headless,   //有浏览器界面启动
                    slowMo: slowMo,       //放慢浏览器执行速度，方便测试观察
                    defaultViewport: {width: width, height: height},
                    args: [            //启动 Chrome 的参数，详见上文中的介绍
                        '--no-sandbox',
                        '--disable-setuid-sandbox',
                        `--window-size=${width2},${height2}`
                    ],
                    timeout: timeout
                });
            } catch (e) {
                console.log("EOO1 打开浏览器失败，异常信息：", e);
                return resolve(null);
            }
            return resolve(browser);
        });
    }

    /**
     * 尝试关闭浏览器
     *
     * 该方法迭代自身直至关闭成功为止
     *
     * 浏览器与puppeteer断开，视作关闭
     *
     * @param browser
     */
    static closeBrowser(browser: Browser): Promise<boolean> {
        return new Promise((resolve) => {
            console.log("browser closeing！")
            if (!browser.isConnected())
                return resolve(true);
            browser.close().then(() => {
                console.log("browser closedone！")
                return resolve(true); // 关闭成功
            }, async rejectInner => {
                console.log("关闭失败，继续尝试，信息：", rejectInner);
                this.closeBrowser(browser).then(resolveOk => {
                    return resolve(resolveOk); // 关闭成功
                });
            })
        });
    }

    /**
     * 分秒格式化
     *
     * 19:2 -> 19:02
     * 9:2  -> 09:02
     * 9:12 -> 09:12
     */
    static formatInMinutesAndSeconds(time: string) {
        let nots: string[] = time.split(":");
        return ((nots[0] + "").length == 1 ? 0 + "" + nots[0] : nots[0]) + ":" + ((nots[1] + "").length == 1 ? 0 + "" + nots[1] : nots[1]);
    }

    /**
     * 倒计时转化为秒
     * 分秒 -> 秒
     * 19:02 -> 19 * 60 + 02
     */
    static countdownConvertedToSecondsOfHHmmToss(time: string) {
        time = this.formatInMinutesAndSeconds(time)
        let nots: string[] = time.split(":");
        return parseInt(nots[0]) * 60 + parseInt(nots[1]);
    }

    /**
     * 鼠标移动
     * @param chooseElement
     * @param page
     */
    static move(chooseElement: ElementHandle, page: Page): Promise<boolean> {
        return new Promise<boolean>(async (resolve, reject) => {
            try {
                if (!(await chooseElement.isIntersectingViewport())) {
                    await chooseElement.screenshot();
                }
                let chooseElementBoxInfo = await chooseElement.boundingBox();
                let whillClickX = chooseElementBoxInfo.x + (chooseElementBoxInfo.width / 2);
                let whillClickY = chooseElementBoxInfo.y + (chooseElementBoxInfo.height / 2);
                await page.mouse.move(whillClickX, whillClickY);
                return resolve(true);
            } catch (e) {
                console.log(e);
                return reject(e);
            }
        });
    }

    /**
     * 鼠标移动并点击
     * @param chooseElement
     * @param page
     */
    static moveAndClic(chooseElement: ElementHandle, page: Page): Promise<boolean> {
        return new Promise<boolean>(async (resolve, reject) => {
            try {
                if (!(await chooseElement.isIntersectingViewport())) {
                    await chooseElement.screenshot();
                }
                await CommonUtils.sleep(500);
                let chooseElementBoxInfo = await chooseElement.boundingBox();
                let whillClickX = chooseElementBoxInfo.x + (chooseElementBoxInfo.width / 2);
                let whillClickY = chooseElementBoxInfo.y + (chooseElementBoxInfo.height / 2);
                await page.mouse.move(whillClickX, whillClickY);
                await CommonUtils.sleep(500);
                await page.mouse.click(whillClickX, whillClickY);
                await CommonUtils.sleep(500);
                return resolve(true);
            } catch (e) {
                console.log("错误", e);
                return reject(e);
            }
        });
    }

    /**
     * 鼠标移动并点击
     *
     * @param chooseElement
     * @param page
     * @param browser
     */
    static moveAndClicAndJump(chooseElement: ElementHandle, page: Page, browser: Browser): Promise<boolean> {
        return new Promise<boolean>(async (resolve, reject) => {
            try {
                await chooseElement.screenshot();
                await CommonUtils.sleep(500);
                let chooseElementBoxInfo = await chooseElement.boundingBox();
                let whillClickX = chooseElementBoxInfo.x + (chooseElementBoxInfo.width / 2);
                let whillClickY = chooseElementBoxInfo.y + (chooseElementBoxInfo.height / 2);
                await page.mouse.move(whillClickX, whillClickY);
                await CommonUtils.sleep(500);
                await page.mouse.click(whillClickX, whillClickY);
                await CommonUtils.sleep(500);
                return resolve(true);
            } catch (e) {
                console.log(e);
                return reject(false);
            }
        });
    }


    /**
     * 获取href与id
     * @param href /zuqiu-6025/
     *
     * @return {href,id} {href:zuqiu-6025,id:6025}
     */
    static getHrefAndId(href: string): { href: string, id: string } {
        href = href.replace(/\//g, "");
        let tdaInfos: string[] = href.split("-");
        let event_id = tdaInfos.length > 1 ? tdaInfos[1] : tdaInfos[0];
        return {href: href, id: event_id};
    }

}